package com.leha.core.services.imp;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.leha.core.constants.CoreErrorDict;
import com.leha.core.dao.*;
import com.leha.core.entity.mybatis.*;
import com.leha.core.entity.vo.GameResVo;
import com.leha.core.entity.vo.UserInfoAndRank;
import com.leha.core.entity.vo.UserRankAndRankList;
import com.leha.core.entity.vo.UserRewardsVO;
import com.leha.core.services.ErrorMessageServices;
import com.leha.core.services.GameServices;
import com.leha.core.services.UserServices;
import com.leha.utils.DateTool;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
@Service
public class GameServicesImpl implements GameServices, InitializingBean {
    @Autowired
    LhGameMapper gameMapper;
    @Autowired
    LhGameLogMapper lhGameLogMapper;
    @Autowired
    LhUserCustomMapper lhUserCustomMapper;
    @Autowired
    LhRankMapper lhRankMapper;
    @Autowired
    LhTopRankMapper lhTopRankMapper;
    @Autowired
    ErrorMessageServices errorMessageServices;
    @Autowired
    LhGameJYLCustomMapper jylCustomMapper;
    @Autowired
    LhRewardItemMapper rewardItemMapper;
    @Autowired
    LhRewardMapper rewardMapper;
    @Autowired
    LhUserShareLogMapper shareLogMapper;
    @Autowired
    LhUserMapper userMapper;
    @Autowired
    UserServices userServices;
    @Autowired
    LhRewardItemMapper lhRewardItemMapper;

    private HashMap<Integer, WxMaService> gameServices;

    @Override
    public WxMaService getGameServices(Integer gameId) {
        return gameServices.get(gameId);
    }

    @Override
    public GameResVo addGameRecord(Integer gameId, Integer uid, Integer osUid, Integer score, Integer osScore, Integer winner) {
        GameResVo res = new GameResVo();
        res.setRankRate(jylCustomMapper.getRankRate(gameId, score));

        LhGameLog log = new LhGameLog();
        log.setGameId(gameId);
        log.setPlayerA(uid);
        log.setPlayerB(osUid);
        log.setPlayeraScore(score);
        log.setPlayerbScore(osScore);
        log.setWinner(winner);
        if(lhGameLogMapper.insertSelective(log)>0) {
            updateUserRank(gameId, uid, score, winner==uid);
            if(osUid!=null && osUid!=0) {
                updateUserRank(gameId, osUid, osScore, winner==osUid);
            }
        } else {
            errorMessageServices.setError(CoreErrorDict.Save_Record_Failed);
            return res;
        }
        res.setResId(log.getResId());
        return res;
    }

    @Override
    public UserRankAndRankList getDailyRank(Integer gameId, Integer limit, Integer uid) {
        UserRankAndRankList ret = new UserRankAndRankList();
        List<UserInfoAndRank> rank = lhUserCustomMapper.getGameDailyRank(gameId, limit);
        for(int i=0;i<rank.size();i++) {
            rank.get(i).setRank(i+1);
            if(uid.equals(rank.get(i).getUid())) {
                UserInfoAndRank rr = new UserInfoAndRank();
                rr.setScore(rank.get(i).getScore());
                rr.setRank(rank.get(i).getRank());
                ret.setSelfRank(rr);
            }
        }
        ret.setRanklist(rank);
        return ret;
    }

    @Override
    public UserRankAndRankList getWeeklyRank(Integer gameId, Integer limit, Integer uid) {
        UserRankAndRankList ret = new UserRankAndRankList();
        List<UserInfoAndRank> rank = lhUserCustomMapper.getGameWeeklyRank(gameId, limit);
        for(int i=0;i<rank.size();i++) {
            rank.get(i).setRank(i+1);
            if(uid.equals(rank.get(i).getUid()))  {
                UserInfoAndRank rr = new UserInfoAndRank();
                rr.setScore(rank.get(i).getScore());
                rr.setRank(rank.get(i).getRank());
                ret.setSelfRank(rr);
            }
        }
        ret.setRanklist(rank);
        return ret;
    }

    @Override
    public UserInfoAndRank userDailyRank(Integer gameId, Integer uid) {
        return lhUserCustomMapper.getUserTodayRankIndex(gameId, uid);
    }

    @Override
    public UserInfoAndRank userWeeklyRank(Integer gameId,Integer uid) {

        return lhUserCustomMapper.getUserWeeklyRankIndex(gameId, uid);
    }

    @Override
    public Boolean removePreWeekRank() {
        return lhTopRankMapper.deleteByExample(new LhTopRankExample())>=0;
    }

    private void initGameMap() {
        gameServices = new HashMap<Integer, WxMaService>();
        LhGameExample ex = new LhGameExample();
        ex.createCriteria().andStatusEqualTo((byte) 0);
        List<LhGame> games = gameMapper.selectByExample(ex);
        for(LhGame game: games) {
            WxMaService wxMaService = new WeixinService(game.getAppid(), game.getSecret(),
                    game.getToken(),game.getAeskey(),game.getMsgdataformat());
            gameServices.put(game.getGid(), wxMaService);
        }
    }

    @Override
    public void Reload() {
        initGameMap();
    }

    @Override
    public List<UserRewardsVO> getGameRewards(Integer gameId) {
        return jylCustomMapper.getGameRewards(gameId, 10);
    }

    @Override
    public List<LhRewardItem> getRewardItem(Integer gameId) {
        LhRewardItemExample ex = new LhRewardItemExample();
        ex.createCriteria().andStatusEqualTo(0);
        return rewardItemMapper.selectByExample(ex);
    }

    @Override
    public List<UserRewardsVO> getMyRewards(Integer gameId, Integer userId, Integer pageNum, Integer pageSize) {
        if(pageNum==null || pageNum==0) pageNum = 1;
        if(pageSize == null) pageSize = 12;
        PageHelper.startPage(pageNum, pageSize);
        return jylCustomMapper.getGameUserRewards(userId);
    }

    @Override
    public Integer userShare(Integer gameId, Integer uid, String sessionKey, String encryptedData, String iv) {
        try{
            String ret = WxMaCryptUtils.decrypt(sessionKey, encryptedData, iv);
            String gid = JSON.parseObject(ret).getString("openGId");
            LhUserShareLog rr = new LhUserShareLog();
            rr.setGid(gid);
            rr.setUid(uid);
            shareLogMapper.insertSelective(rr);
            return userServices.UserCanPlayTimes(uid);
        } catch (Exception e) {
            return 0;
        }

    }

    @Override
    public Boolean userExchange(Integer gameId, Integer uid, Integer recId, Integer itemId, String name, String phone, String address, String email) {
        LhRewardExample ex = new LhRewardExample();
        ex.createCriteria().andUidEqualTo(uid).andItemIdEqualTo(itemId);
        List<LhReward> rewards = rewardMapper.selectByExample(ex);
        if(rewards.size()>0) {
            errorMessageServices.setError(CoreErrorDict.EXCHANGE_Extend);
            return false;
        }
        LhReward reward = new LhReward();
        reward.setGameId(gameId);
        reward.setUid(uid);
        reward.setRecId(recId);
        reward.setItemId(itemId);
        reward.setName(name);
        reward.setPhone(phone);
        reward.setAddress(address);
        reward.setEmail(email);
        reward.setStats(0);
        reward.setInsertTime(new Date());
        rewardMapper.insertSelective(reward);

        LhUser user = new LhUser();
        user.setUid(uid);
        user.setName(name);
        user.setPhone(phone);
        user.setEmail(email);
        user.setAddress(address);
        userMapper.updateByPrimaryKeySelective(user);
        return true;
    }

    @Override
    public LhRewardItem SaveItems(LhRewardItem items) {
        if(items.getItemId()==null || items.getItemId()==0) {
            lhRewardItemMapper.insertSelective(items);
        } else  {
            lhRewardItemMapper.updateByPrimaryKeySelective(items);
        }
        return items;
    }

    @Override
    public List<LhRewardItem> getItems(Integer pgNum, Integer pgSize) {
        PageHelper.startPage(pgNum, pgSize);
        return lhRewardItemMapper.selectByExample(new LhRewardItemExample());
    }

    @Override
    public UserRankAndRankList getTimesRank(Integer gameId, int limit, Integer uid) {
        UserRankAndRankList ret = new UserRankAndRankList();
        List<UserInfoAndRank> rank = lhUserCustomMapper.getGameTimesRank(gameId, limit);
        for(int i=0;i<rank.size();i++) {
            rank.get(i).setRank(i+1);
            if(uid.equals(rank.get(i).getUid())) {
                UserInfoAndRank rr = new UserInfoAndRank();
                rr.setScore(rank.get(i).getScore());
                rr.setRank(rank.get(i).getRank());
                ret.setSelfRank(rr);
            }
        }
        ret.setRanklist(rank);
        return ret;
    }

    @Override
    public UserRankAndRankList getRewardsRank(Integer gameId, int limit, Integer uid) {
        UserRankAndRankList ret = new UserRankAndRankList();
        List<UserInfoAndRank> rank = lhUserCustomMapper.getRewardsRank(gameId, limit);
        for(int i=0;i<rank.size();i++) {
            rank.get(i).setRank(i+1);
            if(uid.equals(rank.get(i).getUid())) {
                UserInfoAndRank rr = new UserInfoAndRank();
                rr.setScore(rank.get(i).getScore());
                rr.setRank(rank.get(i).getRank());
                ret.setSelfRank(rr);
            }
        }
        ret.setRanklist(rank);
        return ret;
    }

    @Override
    public LhRewardItem getItemById(Integer itemId) {
        return lhRewardItemMapper.selectByPrimaryKey(itemId);
    }

    private void updateUserRank(Integer gameId, Integer uid, Integer score, boolean win) {
        lhUserCustomMapper.updateUserScore(uid, win?10:1);
        updateDailyRank(gameId, uid, score);
        updateWeeklyRank(gameId, uid, score);
    }

    private void updateWeeklyRank(Integer gameId, Integer uid, Integer score) {
        LhTopRankExample ex = new LhTopRankExample();
        ex.createCriteria().andGameIdEqualTo(gameId).andPlayerIdEqualTo(uid);
        List<LhTopRank> res = lhTopRankMapper.selectByExample(ex);
        LhTopRank rank;
        if(res.size()>0) {
            rank = res.get(0);
            if(rank.getScore()<score) {
                rank.setScore(score);
                rank.setInsertTime(new Date());
                lhTopRankMapper.updateByPrimaryKeySelective(res.get(0));
            }
        } else {
            rank = new LhTopRank();
            rank.setInsertTime(new Date());
            rank.setScore(score);
            rank.setGameId(gameId);
            rank.setPlayerId(uid);
            lhTopRankMapper.insertSelective(rank);
        }
    }

    private void updateDailyRank(Integer gameId, Integer uid, Integer score) {
        LhRank rank = lhUserCustomMapper.getUserTodayRank(gameId, uid);
        if(rank==null) {
            rank = new LhRank();
            rank.setGameId(gameId);
            rank.setPlayerId(uid);
            rank.setScore(score);
            lhRankMapper.insertSelective(rank);
        } else if(rank.getScore()<score) {
            rank.setScore(score);
            lhRankMapper.updateByPrimaryKeySelective(rank);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initGameMap();
    }
}
